package com.bbcare.treat.plat.service.impl;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

import com.bbcare.comm.AppException;
import com.bbcare.comm.Constants;
import com.bbcare.comm.DateUtil;
import com.bbcare.comm.ErrorCode;
import com.bbcare.comm.SeqUtil;
import com.bbcare.comm.ToolUtils;
import com.bbcare.department.plat.entity.DepartmentBasic;
import com.bbcare.department.plat.service.IBsSmsTemplateService;
import com.bbcare.department.plat.store.ibatis.IDeparmentBasicDao;
import com.bbcare.followup.plat.entity.ContentTempl;
import com.bbcare.followup.plat.entity.ContentTemplVersion;
import com.bbcare.followup.plat.entity.FollowQueue;
import com.bbcare.followup.plat.entity.FollowScheme;
import com.bbcare.followup.plat.entity.FollowSchemeVersion;
import com.bbcare.followup.plat.entity.FollowTask;
import com.bbcare.followup.plat.entity.FollowTaskContent;
import com.bbcare.followup.plat.entity.FuTaskRule;
import com.bbcare.followup.plat.entity.Patient;
import com.bbcare.followup.plat.entity.PatientQueueScheme;
import com.bbcare.followup.plat.entity.PatientTask;
import com.bbcare.followup.plat.entity.PatientTaskContent;
import com.bbcare.followup.plat.entity.PtAccountInfo;
import com.bbcare.followup.plat.entity.PtLostRd;
import com.bbcare.followup.plat.entity.PtUserextendInfo;
import com.bbcare.followup.plat.service.IPatientInfoHisService;
import com.bbcare.followup.plat.service.IPatientService;
import com.bbcare.followup.plat.store.ibatis.IConfCacheDAO;
import com.bbcare.followup.plat.store.ibatis.IContentTemplDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowQueueDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowSchemeDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowTaskContentDAO;
import com.bbcare.followup.plat.store.ibatis.IFollowTaskDAO;
import com.bbcare.followup.plat.store.ibatis.IFuTaskRuleDao;
import com.bbcare.followup.plat.store.ibatis.IPatientAccountDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientExtendDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientOperationRecordDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientQueueSchemeDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientTaskContentDAO;
import com.bbcare.followup.plat.store.ibatis.IPatientTaskDAO;
import com.bbcare.plat.redis.service.IPatientQueueRedis;
import com.bbcare.treat.plat.entity.FuQueueScheme;
import com.bbcare.treat.plat.entity.PtArchiveData;
import com.bbcare.treat.plat.entity.PtArchiveTask;
import com.bbcare.treat.plat.entity.PtFuQueue;
import com.bbcare.treat.plat.entity.PtQueueSchemeRel;
import com.bbcare.treat.plat.entity.PtTrQueue;
import com.bbcare.treat.plat.entity.TrScheme;
import com.bbcare.treat.plat.entity.TrSchemeVersion;
import com.bbcare.treat.plat.entity.TrTask;
import com.bbcare.treat.plat.service.IDealWithEyesCreate;
import com.bbcare.treat.plat.service.IPatientArchService;
import com.bbcare.treat.plat.service.IPatientTreatService;
import com.bbcare.treat.plat.store.ibatis.IFuQueueSchemeDAO;
import com.bbcare.treat.plat.store.ibatis.IPtArchiveDataDAO;
import com.bbcare.treat.plat.store.ibatis.IPtArchiveTaskDAO;
import com.bbcare.treat.plat.store.ibatis.IPtFuQueueDAO;
import com.bbcare.treat.plat.store.ibatis.IPtQueueSchemeRelDAO;
import com.bbcare.treat.plat.store.ibatis.IPtTrOprDAO;
import com.bbcare.treat.plat.store.ibatis.IPtTrQueueDAO;
import com.bbcare.treat.plat.store.ibatis.ITrSchemeDAO;
import com.bbcare.treat.plat.store.ibatis.ITrTaskDAO;

/**
 * @name: 患者门诊诊疗相关接口实现
 * @author: DemonLee
 * @createTime: 2017.8.15
 * @description:
 * @modify:
 *
 */
@Service
public class PatientTreatService implements IPatientTreatService {
    private final Log logger = LogFactory.getLog(PatientTreatService.class);

    @Autowired
    private IFollowQueueDAO queueDao;

    @Autowired
    private IFollowTaskDAO followTaskDao;

    @Autowired
    private ITrTaskDAO trTaskDao;

    @Autowired
    private IFuQueueSchemeDAO fuQueueSchemeDao;

    @Autowired
    private IFollowSchemeDAO followSchemeDao;

    @Autowired
    private ITrSchemeDAO trSchemeDao;

    @Autowired
    private IContentTemplDAO contentTemplDao;

    @Autowired
    private IPatientService patientService;

    @Autowired
    private IPtQueueSchemeRelDAO ptQueueSchemeRelDao;

    @Autowired
    private IPtArchiveDataDAO ptArchiveDataDao;

    @Autowired
    private IPtTrQueueDAO ptTrQueueDao;

    @Autowired
    private IPtFuQueueDAO ptFuQueueDao;

    @Autowired
    private IPatientAccountDAO ptAccountDao;

    @Autowired
    private IPatientQueueSchemeDAO patientQueueSchemeDao;

    @Autowired
    private IPatientService patientSerivce;

    @Autowired
    private IPatientInfoHisService patientInfoHisService;

    @Autowired
    private IPatientOperationRecordDAO patientOperationRecordDao;

    @Autowired
    public IConfCacheDAO confCacheDao;

    @Autowired
    private IBsSmsTemplateService bsSmsTemplateService;

    @Autowired
    private IDeparmentBasicDao deparmentBasicDao;

    @Autowired
    private IPatientQueueRedis ptQueueRedis;

    @Autowired
    private IPatientTaskDAO patientTaskDao;

    @Autowired
    private IFollowTaskContentDAO followTaskContDao;

    @Autowired
    private IPatientTaskContentDAO patientTaskConDao;

    @Autowired
    private IFuTaskRuleDao fuTaskRuleDao;

    @Autowired
    private IPatientDAO patientDao;

    @Autowired
    private IPtArchiveTaskDAO ptArchiveTaskDao;

    @Autowired
    private IPatientExtendDAO ptExtendDao;

    @Autowired
    private IPtTrOprDAO ptTrOprDao;

    @Autowired
    private IPatientArchService patientArchService;

    @Autowired
    private IDealWithEyesCreate DealWithEyesCreate;

    @Resource(name = "jedisPool")
    private JedisPool jedisPool;

    // 根据队列id查询当前专病的任务接口实现
    @Override
    public Map<String, Object> listSpecialTask(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();
        List<Map<String, Object>> taskList = new ArrayList<Map<String, Object>>();
        retOut.put("rows", taskList);
        retOut.put("total", 0);

        String queueId = (String) argMap.get("followQueueId");
        Integer schemeBusiType = (Integer) argMap.get("schemeBusiType");
        String ptSchemeId = (String) argMap.get("ptSchemeId");

        // 队列信息校验
        Map<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (CollectionUtils.isEmpty(queueList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "根据队列id未查询到队列信息！"));
        }
        FollowQueue fq = (FollowQueue) queueList.get(0);
        if (!Constants.QUEUE_STATUS_NOMAL.equals(fq.getQueueStatus())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_STATUS_IRREGULAR, "队列状态不正常，无法查询对应任务！"));
        }
        retOut.put("queueName", fq.getQueueName());

        // 建档内容跟随队列走
        String archiveTemplId = fq.getArchiveTemplId();// 建档问卷模板id
        String archiveTaskId = fq.getArchiveTaskId();// 建档任务配置id
        if (StringUtils.isEmpty(archiveTemplId)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEMEID_ARCHIVE_TASKCONT_NOT_EXIST,
                    "队列下未配置建档任务内容！"));
        }
        if (StringUtils.isEmpty(archiveTaskId)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEMEID_ARCHIVE_TASK_NOT_EXIST,
                    "队列下未配置建档任务id！"));
        }
        Map<String, Object> archTaskMap = new HashMap<String, Object>();
        archTaskMap.put("task_id", archiveTaskId);
        archTaskMap.put("task_name", "建档");
        archTaskMap.put("seq_no", Constants.TASK_SEQ_FOR_INIT);
        taskList.add(archTaskMap);

        retOut.put("total", taskList.size());
        // retOut.put("schemeId", "");
        // retOut.put("schemeName", "");

        String schemeId = "";
        String schemeVersionid = "";
        // String schemeName = "";
        // 患者没建档
        if (StringUtils.isBlank(ptSchemeId)) {
            // 查询队列方案关联信息表
            Map<String, Object> qryMapIn = new HashMap<String, Object>();
            qryMapIn.put("queueId", queueId);
            qryMapIn.put("seqNo", Constants.QUEUE_DEFAULT_SCHEME_SEQ_NO);// 默认方案
            qryMapIn.put("schemeBusiType", schemeBusiType);
            List<FuQueueScheme> fuQueueSchemeList = fuQueueSchemeDao.listByQueueId(qryMapIn);
            if (CollectionUtils.isEmpty(fuQueueSchemeList)) {
                qryMapIn.remove("seqNo");
                // 没有默认方案，则查询当前类型下所有，取其中一个
                fuQueueSchemeList = fuQueueSchemeDao.listByQueueId(qryMapIn);
                if (CollectionUtils.isEmpty(fuQueueSchemeList)) {
                    return retOut;
                }
            }
            FuQueueScheme fuQueueSchemeVo = fuQueueSchemeList.get(0);

            // 获取方案（版本）信息
            schemeId = fuQueueSchemeVo.getSchemeId();
            if (StringUtils.isEmpty(schemeId)) {
                return retOut;
            }
            Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
            qrySchemeMap.put("schemeId", schemeId);
            qrySchemeMap.put("schemeBusiType", schemeBusiType);
            Map<String, Object> qrySchemeOut = this.getMultiSchemeInfo(qrySchemeMap);
            schemeVersionid = (String) qrySchemeOut.get("schemeVersionid");
            // schemeName = (String) qrySchemeOut.get("schemeName");
        } else {
            // 患者已经建档（后续还要根据pt_trtask_info进行修改）
            Map<String, Object> relMapIn = new HashMap<String, Object>();
            relMapIn.put("ptSchemeId", ptSchemeId);
            relMapIn.put("schemeBusiType", schemeBusiType);
            relMapIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
            List<PtQueueSchemeRel> psRelList = ptQueueSchemeRelDao.listPtQueueSchemeRel(relMapIn);
            if (CollectionUtils.isEmpty(psRelList)) {
                // 建档过，但没有选择任何方案
                return retOut;
            }
            PtQueueSchemeRel psRelVo = psRelList.get(0);
            schemeId = psRelVo.getSchemeId();
            schemeVersionid = psRelVo.getSchemeVersionid();
        }

        // 获取方案版本
        if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType) {
            // 科研随访方案
            Map<String, Object> taskQueryParam = new HashMap<String, Object>();
            taskQueryParam.put("schemeVersionid", schemeVersionid);
            taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 0：门诊随访
            List<FollowTask> fuTaskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
            if (CollectionUtils.isEmpty(fuTaskList)) {
                logger.warn("当前随访方案版本id【" + schemeVersionid + "】对应任务列表为空！");
                return retOut;
            }
            int fusize = fuTaskList.size();
            int fu = 0;
            FollowTask fuTaskVo = new FollowTask();
            int seqNo = 0;
            for (fu = 0; fu < fusize; fu++) {
                fuTaskVo = fuTaskList.get(fu);
                seqNo = fuTaskVo.getSeqNo();
                if (Constants.TASK_SEQ_FOR_INIT == seqNo) {
                    // 去掉建档任务（建档随队列走）
                    continue;
                }
                Map<String, Object> taskMap = new HashMap<String, Object>();
                taskMap.put("task_id", fuTaskVo.getId());
                taskMap.put("task_name", fuTaskVo.getTaskName());
                taskMap.put("seq_no", seqNo);

                taskList.add(taskMap);
            }
        } else if (Constants.SCHEME_BUSI_TYPE_1 == schemeBusiType) {
            // 门诊诊疗方案
            Map<String, Object> taskQueryParam = new HashMap<String, Object>();
            taskQueryParam.put("schemeVersionid", schemeVersionid);
            taskQueryParam.put("revSeqNo", Constants.TASK_SEQ_FOR_INIT);// 剔除建档任务
            List<TrTask> trTaskList = trTaskDao.listTrTaskBySchemeVersionid(taskQueryParam);
            if (CollectionUtils.isEmpty(trTaskList)) {
                logger.warn("当前诊疗方案版本id【" + schemeVersionid + "】对应任务列表为空！");
                return retOut;
            }
            int fusize = trTaskList.size();
            int fu = 0;
            TrTask fuTaskVo = new TrTask();
            int seqNo = 0;
            for (fu = 0; fu < fusize; fu++) {
                fuTaskVo = trTaskList.get(fu);
                seqNo = fuTaskVo.getSeqNo();
                Map<String, Object> taskMap = new HashMap<String, Object>();
                taskMap.put("task_id", fuTaskVo.getId());
                taskMap.put("task_name", fuTaskVo.getTaskName());
                taskMap.put("seq_no", seqNo);

                taskList.add(taskMap);
            }
        } else {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEME_BUSITYPE_INCOMPATIBLE,
                    "暂不支持该方案业务类型: [" + schemeBusiType + "]！"));
        }
        // retOut.put("schemeId", schemeId);
        // retOut.put("schemeName", schemeName);
        retOut.put("rows", taskList);
        retOut.put("total", taskList.size());

        return retOut;
    }

    // 公共方法，获取方案（版本）信息
    @Override
    public Map<String, Object> getMultiSchemeInfo(Map<String, Object> mapIn) throws Exception {
        Map<String, Object> retOut = new HashMap<String, Object>();
        String schemeId = (String) mapIn.get("schemeId");
        Integer schemeBusiType = (Integer) mapIn.get("schemeBusiType");
        String schemeVersionId = "";// 方案版本id
        String schemeName = "";// 方案名称

        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        qrySchemeMap.put("id", schemeId);
        if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType) {
            // 科研随访方案
            List<FollowScheme> fsList = followSchemeDao.selectById(qrySchemeMap);
            if (CollectionUtils.isEmpty(fsList)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "随访方案不存在，处理失败!"));
            }
            FollowScheme fshVo = fsList.get(0);

            Map<String, Object> qrySchemeVerMap = new HashMap<String, Object>();
            qrySchemeVerMap.put("schemeId", schemeId);
            qrySchemeVerMap.put("schemeVersion", fshVo.getNewVersion());
            List<FollowSchemeVersion> fsvList = followSchemeDao.selectBySchemeIdAndVersion(qrySchemeVerMap);
            if (CollectionUtils.isEmpty(fsvList)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "随访方案版本记录不存在!"));
            }
            FollowSchemeVersion fsvVo = fsvList.get(0);

            schemeName = fshVo.getSchemeName();
            schemeVersionId = fsvVo.getId();
        } else if (Constants.SCHEME_BUSI_TYPE_1 == schemeBusiType) {
            // 门诊诊疗方案
            List<TrScheme> fsList = trSchemeDao.getTrSchemeById(qrySchemeMap);
            if (CollectionUtils.isEmpty(fsList)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEME_NOT_EXIST, "诊疗方案不存在，处理失败!"));
            }
            TrScheme trShVo = fsList.get(0);

            Map<String, Object> qrySchemeVerMap = new HashMap<String, Object>();
            qrySchemeVerMap.put("schemeId", schemeId);
            qrySchemeVerMap.put("schemeVersion", trShVo.getNewVersion());
            List<TrSchemeVersion> fsvList = trSchemeDao.getTrSchemeBySchemeVersion(qrySchemeVerMap);
            if (CollectionUtils.isEmpty(fsvList)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_SCHEMEVERSION_NOT_EXIST, "诊疗方案版本记录不存在!"));
            }
            TrSchemeVersion trShVerVo = fsvList.get(0);

            schemeName = trShVo.getSchemeName();
            schemeVersionId = trShVerVo.getId();
        } else {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEME_BUSITYPE_INCOMPATIBLE,
                    "暂不支持该方案业务类型: [" + schemeBusiType + "]！"));
        }
        retOut.put("schemeVersionid", schemeVersionId);
        retOut.put("schemeName", schemeName);

        return retOut;
    }

    // 查询队列建档问卷内容接口实现
    @Override
    public Map<String, Object> getQueueArchiveContent(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();
        String queueId = (String) argMap.get("followQueueId");
        String ptSchemeId = (String) argMap.get("ptSchemeId");

        // 队列信息校验
        Map<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (CollectionUtils.isEmpty(queueList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "根据队列id未查询到队列信息！"));
        }
        FollowQueue fq = (FollowQueue) queueList.get(0);
        if (!Constants.QUEUE_STATUS_NOMAL.equals(fq.getQueueStatus())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_STATUS_IRREGULAR, "队列状态不正常，无法处理！"));
        }

        // 建档内容跟随队列走
        String archiveTemplId = fq.getArchiveTemplId();// 建档任务内容模板id
        String archiveTaskId = fq.getArchiveTaskId();// 建档任务配置id
        if (StringUtils.isEmpty(archiveTemplId)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEMEID_ARCHIVE_TASKCONT_NOT_EXIST,
                    "队列下未配置建档任务内容！"));
        }
        if (StringUtils.isEmpty(archiveTaskId)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEMEID_ARCHIVE_TASK_NOT_EXIST,
                    "队列下未配置建档任务id！"));
        }

        // 多个任务内容id用逗号（,）分隔
        String archiveTemplIdArr[] = archiveTemplId.split(Constants.COMMA_SPLIT_STR);
        List<String> archiveTemplIdList = java.util.Arrays.asList(archiveTemplIdArr);
        Map<String, Object> contMapIn = new HashMap<String, Object>();
        contMapIn.put("templIdList", archiveTemplIdList);
        Map<String, Object> contMapOut = this.getContentTemplData(contMapIn);
        retOut.put("questiones", contMapOut.get("questiones"));

        // 建档后将答案一起查询出来
        if (StringUtils.isNotBlank(ptSchemeId)) {
            Map<String, Object> queueMapIn = new HashMap<String, Object>();
            queueMapIn.put("id", ptSchemeId);
            queueMapIn.put("queueId", queueId);
            List<PatientQueueScheme> pqsList = patientQueueSchemeDao.selectPatientByCondition(queueMapIn);
            if (!CollectionUtils.isEmpty(pqsList)) {
                PatientQueueScheme pqsVo = pqsList.get(0);
                Map<String, Object> archMapIn = new HashMap<String, Object>();
                archMapIn.put("ptSchemeId", ptSchemeId);
                archMapIn.put("queueId", queueId);
                archMapIn.put("ptTaskId", pqsVo.getArchiveTaskId());
                archMapIn.put("userId", pqsVo.getUserId());
                Map<String, Object> archMapOut = this.getPtArchInfo(archMapIn);
                archMapOut.put("archiveTaskId", pqsVo.getArchiveTaskId());
                archMapOut.put("ptSchemeId", ptSchemeId);
                archMapOut.put("patientId", pqsVo.getUserId());
                retOut.put("archivesInfo", archMapOut);

                // 患者基本信息
                Map<String, Object> userMap = new HashMap<String, Object>();
                userMap.put("userId", pqsVo.getUserId());
                userMap.put("tenantId", pqsVo.getTenantId());
                Patient ptVo = patientDao.selectById(userMap);
                if (null == ptVo) {
                    throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
                }
                retOut.put("patientInfo", ptVo);
            }
        }
        retOut.put("followQueueId", queueId);

        return retOut;
    }

    // 根据任务内容模板id查询问卷内容通用接口实现
    @Override
    public Map<String, Object> getContentTemplData(Map<String, Object> paramIn) throws Exception {
    	String questionnaireType = (String)paramIn.get("questionnaireType");

        Map<String, Object> argMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>(paramIn);

        List<Object> conDataList = new ArrayList<Object>();
        List<String> templIdList = ToolUtils.typeCast(argMap.get("templIdList"));
        if (CollectionUtils.isEmpty(templIdList)) {
            return retOut;
        }
        int templIdSize = templIdList.size();
        int kq = 0;
        String conTemplId = "";
        Map<String, Object> contVerMap = new HashMap<String, Object>();
        Map<String, Object> dataOut = new HashMap<String, Object>();
        for (kq = 0; kq < templIdSize; kq++) {
            conTemplId = (String) templIdList.get(kq);
            if (StringUtils.isEmpty(conTemplId)) {
                continue;
            }

            // 获取内容模板
            Map<String, Object> templMap = new HashMap<String, Object>();
            templMap.put("id", conTemplId);
            List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
            if (CollectionUtils.isEmpty(ctList)) {
                continue;
            }
            ContentTempl conVo = ctList.get(0);

            //如果通过问卷类型来获取问卷模板内容
            if(!StringUtils.isEmpty(questionnaireType) && !questionnaireType.equals(conVo.getTemplType())){
            	continue;
            }

            // 获取内容模板版本
            contVerMap.clear();
            contVerMap.put("templId", conVo.getId());
            contVerMap.put("templVersion", conVo.getNewVersion());
            List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
            if (CollectionUtils.isEmpty(ctvList)) {
                continue;
            }
            ContentTemplVersion ctv = ctvList.get(0);

            dataOut.clear();
            contVerMap.clear();
            contVerMap.put("templVersionId", ctv.getId());
            dataOut = patientService.getContTemplData(contVerMap);
            if (null != dataOut.get("contData")) {
                conDataList.add(dataOut.get("contData"));
            }
        }
        retOut.put("questiones", conDataList);

        return retOut;
    }

    // 通用版患者建档接口实现（兼容各种方案）
    @Transactional
    public Map<String, Object> savePatientArchives(Map<String, Object> servParamMap) throws Exception {
        logger.debug("savePatientArchives arg==" + servParamMap.toString());

        List<Map<String, Object>> schemeList = ToolUtils.typeCast(servParamMap.get("schemeList"));
        Patient pt = (Patient) servParamMap.get("patient");

        String deptId = (String) servParamMap.get("deptId");
        String queueId = (String) servParamMap.get("queueId");
        String updateTime = (String) servParamMap.get("updateTime");
        String authorId = (String) servParamMap.get("authorId");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String tenantId = (String) servParamMap.get("tenantId");
        String authorName = (String) servParamMap.get("authorName");
        String opCode = (String) servParamMap.get("opCode");
        String opType = (String) servParamMap.get("opType");
        String phoneNo = pt.getPhoneNo();
        Map<String, Object> quesMap = ToolUtils.typeCast(servParamMap.get("contentData"));

        String fromQueueId = (null == servParamMap.get("fromQueueId")) ? null
                : String.valueOf(servParamMap.get("fromQueueId"));
        String fromQueueSchemeId = (String) servParamMap.get("fromQueueSchemeId");

        // 先锁表，防止同一个队列并发添加患者
        FollowQueue upQueue = new FollowQueue();
        upQueue.setId(queueId);
        upQueue.setUpdateTime(updateTime);
        int queRet = queueDao.updateQueue(upQueue);
        if (0 == queRet) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }

        // 队列信息校验
        Map<String, Object> queueMapIn = new HashMap<String, Object>();
        queueMapIn.put("queueId", queueId);
        queueMapIn.put("tenantId", tenantId);
        Map<String, Object> queueMapOut = this.dealFuQueueInfo(queueMapIn);
        FollowQueue fq = (FollowQueue) queueMapOut.get("queueInfo");
        String queueName = fq.getQueueName();
        String newTenantId = (String) queueMapOut.get("tenantId");
        if (StringUtils.isNotBlank(newTenantId)) {
            tenantId = newTenantId;
            servParamMap.put("tenantId", newTenantId);
        }
        // 扫码建档，队列审核状态
        String auditType = fq.getAuditType();
        if (StringUtils.isBlank(auditType)) {
            auditType = "";
        }
        String archiveTaskId = fq.getArchiveTaskId();
        servParamMap.put("archiveTaskId", archiveTaskId);
        servParamMap.put("archiveTemplId", fq.getArchiveTemplId());

        // 校验账户信息
        String ptAccountId = "";// 账号id
        HashMap<String, Object> qryPtMap = new HashMap<String, Object>();
        qryPtMap.put("phoneNo", phoneNo);
        List<PtAccountInfo> ptAcList = ptAccountDao.selectPtAccountByPhoneNo(qryPtMap);
        if (null != ptAcList && 0 != ptAcList.size()) {
            PtAccountInfo ptAcVo = ptAcList.get(0);
            ptAccountId = ptAcVo.getId();
        } else {
            ptAccountId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_ACCOUNTID);
            PtAccountInfo ptAcVo = new PtAccountInfo();
            ptAcVo.setAccountName((String) servParamMap.get("matherName"));// 暂填母亲姓名
            ptAcVo.setAuthorId(authorId);
            ptAcVo.setCreateTime(updateTime);
            ptAcVo.setId(ptAccountId);
            ptAcVo.setPhoneNo(phoneNo);
            ptAcVo.setRemark("建档新增");
            ptAcVo.setUpdateTime(updateTime);
            ptAccountDao.savePatientAccountInfo(ptAcVo);
        }

        // 校验患者信息（是否已经建档）
        Map<String, Object> userInMap = new HashMap<String, Object>();
        userInMap.put("updateTime", updateTime);
        userInMap.put("updateAccept", updateAccept);
        userInMap.put("phoneNo", phoneNo);
        userInMap.put("userName", pt.getUserName());
        userInMap.put("tenantId", tenantId);
        userInMap.put("patient", pt);
        userInMap.put("queueId", queueId);
        userInMap.put("authorId", authorId);
        userInMap.put("ptAccountId", ptAccountId);
        Map<String, Object> userOutMap = patientSerivce.dealPtBasicInfo(userInMap);
        String userId = (String) userOutMap.get("userId");
        int redisFlag = (Integer) userOutMap.get("redisFlag");
        if (null != userOutMap.get("patient")) {
            pt = (Patient) userOutMap.get("patient");
            servParamMap.put("patient", pt);
        }

        // 入操作流水记录表 ia_operation_record
        String opUserType = Constants.OPCODE_TYPE_DOCTOR;
        if (Constants.OP_TYPE_SELF.equals(pt.getSourceType())) {
            opUserType = Constants.OPCODE_TYPE_PATIENT;
        }
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", pt.getUserName());
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        if (Constants.OP_CODE_1004.equals(opCode)) {// 队列患者转移
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_11);
        } else if ((Constants.OP_CODE_1000.equals(opCode))) {
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_7);
        }
        paramRecord.put("opUsertype", opUserType);
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        if (StringUtils.isBlank((String) servParamMap.get("opNote"))) {
            String remark = "患者" + pt.getUserName() + "通过app进行主诉登记";
            paramRecord.put("remark", remark);
        } else {
            paramRecord.put("remark", (String) servParamMap.get("opNote"));
        }
        paramRecord.put("opType", opType);

        // 校验患者是否已经加入过该队列
        PatientQueueScheme pts = new PatientQueueScheme();
        Map<String, Object> ptQueueMapIn = new HashMap<String, Object>();
        ptQueueMapIn.put("queueId", queueId);
        ptQueueMapIn.put("userId", userId);
        ptQueueMapIn.put("userName", pt.getUserName());
        ptQueueMapIn.put("queueName", queueName);
        ptQueueMapIn.put("updateTime", updateTime);
        ptQueueMapIn.put("questiones", quesMap);
        ptQueueMapIn.put("ptQueueSchemeInfo", pts);
        Map<String, Object> ptQueueMapOut = this.dealPtQueueInfo(ptQueueMapIn);
        pts = (PatientQueueScheme) ptQueueMapOut.get("ptQueueSchemeInfo");

        // 入患者队列信息表 pt_queuescheme_info
        String ptQueueSchemeId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTSCHEMEID);
        String cardStatus = (String) servParamMap.get("card_status");
        String cardType = (String) servParamMap.get("card_type");
        String cardNo = (String) servParamMap.get("card_no");
        pts.setId(ptQueueSchemeId);
        pts.setAuthorId(authorId);
        pts.setCreateTime(updateTime);
        pts.setUpdateTime(updateTime);
        pts.setQueueId(queueId);
        pts.setSchemeId("");// 暂时空，后续将该字段废弃
        pts.setSchemeVersionid("");// 暂时空，后续将该字段废弃
        pts.setUserId(pt.getId());
        pts.setTotalNum(0);// 暂时空，后续将该字段废弃
        pts.setUpdateAccept(updateAccept);
        pts.setUpdateAuthor(authorId);
        pts.setFinishNum(0);// 暂时空，后续将该字段废弃
        pts.setCardNo(cardNo);
        pts.setCardStatus(cardStatus);
        pts.setCardType(cardType);
        // 诊间扫码渠道建档，需要审核，modify by DemonLee 2018.3.7
        pts.setUserStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        pts.setConfirmFlag(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_SUCCESS);
        //转归类型 20180329
        pts.setChangeStatus(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CHANGE_STATUS);
        String ptSourceType = pt.getSourceType();
        if (StringUtils.isNotBlank(ptSourceType) && Constants.PATIENT_SOURCE_TYPE_SCAN.equals(ptSourceType)) {
            // 审核类型为空或事后审核（事先审核走其他逻辑：预处理转正式）
            if (StringUtils.isBlank(auditType) || Constants.QUEUE_AUDIT_TYPE_FOR_PAST.equals(auditType)) {
                pts.setConfirmFlag(Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_INIT);
            }
        }
        servParamMap.put("sourceType", ptSourceType);

        // 查询方案版本
        int schsize = schemeList.size();
        int sch = 0;
        Map<String, Object> schemeMap = new HashMap<String, Object>();
        Integer schemeBusiType = 0;
        String schemeId = "";
        String schemeVersionId = "";
        // String schemeName = "";
        // 可能一个方案也没有
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        for (sch = 0; sch < schsize; sch++) {
            schemeMap = schemeList.get(sch);
            schemeBusiType = (Integer) schemeMap.get("schemeBusiType");
            schemeId = (String) schemeMap.get("schemeId");

            qrySchemeMap.clear();
            qrySchemeMap.put("schemeId", schemeId);
            qrySchemeMap.put("schemeBusiType", schemeBusiType);
            Map<String, Object> qrySchemeOut = this.getMultiSchemeInfo(qrySchemeMap);
            schemeVersionId = (String) qrySchemeOut.get("schemeVersionid");
            // schemeName = (String) qrySchemeOut.get("schemeName");

            servParamMap.put("userId", userId);
            servParamMap.put("ptQueueSchemeId", ptQueueSchemeId);
            servParamMap.put("schemeVersionId", schemeVersionId);
            servParamMap.put("schemeId", schemeId);
            servParamMap.put("schemeBusiType", schemeBusiType);
            if (Constants.SCHEME_BUSI_TYPE_0 == schemeBusiType) {
                // 科研随访方案实例化
                this.dealPtFuTaskIns(servParamMap);
                // taskId_0 = (String) insOutMap.get("taskId_0");
            } else if (Constants.SCHEME_BUSI_TYPE_1 == schemeBusiType) {
                // 门诊诊疗方案实例化
                PtTrQueue ptTrQueue = new PtTrQueue();
                ptTrQueue.setAuthorId(authorId);
                ptTrQueue.setCreateTime(updateTime);
                ptTrQueue.setFinishNum(0);
                ptTrQueue.setPtSchemeId(ptQueueSchemeId);
                ptTrQueue.setQueueId(queueId);
                ptTrQueue.setSchemeBusiType(schemeBusiType);
                ptTrQueue.setSchemeId(schemeId);
                ptTrQueue.setSchemeVersionid(schemeVersionId);
                ptTrQueue.setStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
                ptTrQueue.setUpdateAccept(updateAccept);
                ptTrQueue.setUpdateAuthor(authorId);
                ptTrQueue.setUpdateTime(updateTime);
                ptTrQueue.setUserId(userId);
                ptTrQueue.setTenantId(tenantId);
                ptTrQueueDao.savePtTrQueue(ptTrQueue);// pt_trqueue_info
                Map<String, Object> ptTrQueueMapIn = new HashMap<String, Object>();
                ptTrQueueMapIn.put("ptSchemeId", ptQueueSchemeId);
                ptTrQueueMapIn.put("updateType", Constants.UPDATE_TYPE_INSERT);
                ptTrQueueDao.savePtTrQueueHis(ptTrQueueMapIn);// pt_trqueue_info_his
            } else {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_SCHEME_BUSITYPE_INCOMPATIBLE,
                        "暂不支持该方案业务类型: [" + schemeBusiType + "]！"));
            }

            // 入患者队列方案关联信息: pt_queueschemerel_info
            PtQueueSchemeRel ptQueueSchemeRel = new PtQueueSchemeRel();
            ptQueueSchemeRel.setAuthorId(authorId);
            ptQueueSchemeRel.setCreateTime(updateTime);
            ptQueueSchemeRel.setPtSchemeId(ptQueueSchemeId);
            ptQueueSchemeRel.setQueueId(queueId);
            ptQueueSchemeRel.setSchemeBusiType(schemeBusiType);
            ptQueueSchemeRel.setSchemeId(schemeId);
            ptQueueSchemeRel.setSchemeVersionid(schemeVersionId);
            ptQueueSchemeRel.setStatus(Constants.TABLE_RECORD_STATUS_NOMAL);
            ptQueueSchemeRel.setUpdateAccept(updateAccept);
            ptQueueSchemeRel.setUpdateTime(updateTime);
            ptQueueSchemeRel.setUserId(userId);
            ptQueueSchemeRel.setTenantId(tenantId);
            ptQueueSchemeRelDao.savePtQueueSchemeRel(ptQueueSchemeRel);
        }
        Map<String, Object> insertPtQueueMap = new HashMap<String, Object>();
        insertPtQueueMap.put("id", ptQueueSchemeId);
        insertPtQueueMap.put("updateTime", pts.getUpdateTime());
        insertPtQueueMap.put("updateAuthor", pts.getUpdateAuthor());
        insertPtQueueMap.put("updateAccept", pts.getUpdateAccept());
        insertPtQueueMap.put("updateType", Constants.UPDATE_TYPE_INSERT);

        // 建档内容随队列走（不随方案走）
        Map<String, Object> archOutMap = this.savePtQueueArchives(servParamMap);
        String ptArchiveTaskId = (String) archOutMap.get("ptArchiveTaskId");
        paramRecord.put("taskId", ptArchiveTaskId);

        pts.setArchiveTaskId(ptArchiveTaskId);
        pts.setTenantId(tenantId);
        patientQueueSchemeDao.savePatientQueueSchemeInfo(pts);
        patientQueueSchemeDao.insertPatientQueueSchemeHis(insertPtQueueMap);

        if (null != fromQueueId) {// 转移队列时 需将原队列患者状态置为转移状态 并插入一条历史记录
            Map<String, Object> updateQueueMap = new HashMap<String, Object>();
            updateQueueMap.put("id", fromQueueSchemeId);// ID
            updateQueueMap.put("queueId", fromQueueId);// ID
            updateQueueMap.put("updateTime", updateTime);
            updateQueueMap.put("updateAuthor", authorId);
            updateQueueMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_TRANSFER);
            updateQueueMap.put("oldStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
            updateQueueMap.put("updateAccept", updateAccept);
            updateQueueMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);

            // 转以后 更新原队列当前人数-1 fu_queue_info
            FollowQueue fromFqueueVo = new FollowQueue();
            fromFqueueVo.setCurrNum(1);
            fromFqueueVo.setId(fromQueueId);
            fromFqueueVo.setUpdateTime(updateTime);
            queueDao.updateQueueTransfer(fromFqueueVo);

            patientQueueSchemeDao.updatePtQueueSchemeRecord(updateQueueMap);
            patientQueueSchemeDao.insertPatientQueueSchemeHis(updateQueueMap);
        }

        // 若有建档任务，则将建档任务id入操作记录表
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        // 同步患者信息
        Map<String, Object> synchMapIn = new HashMap<String, Object>();
        synchMapIn.put("ptSchemeId", ptQueueSchemeId);
        synchMapIn.put("queueId", queueId);
        synchMapIn.put("authorId", authorId);
        synchMapIn.put("tenantId", tenantId);
        synchMapIn.put("redisFlag", redisFlag);
        synchMapIn.put("queueName", queueName);
        synchMapIn.put("deptId", deptId);
        synchMapIn.put("patientInfo", pt);
        synchMapIn.put("smsFlag", fq.getSmsFlag());
        this.dealPtSynchInfo(synchMapIn);

        Map<String, Object> outRet = new HashMap<String, Object>();
        outRet.put("patientId", userId);
        outRet.put("ptSchemeId", ptQueueSchemeId);
        // outRet.put("archiveTaskId", ptArchiveTaskId);

        return outRet;
    }

    /**
     * 队列配置信息校验
     */
    public Map<String, Object> dealFuQueueInfo(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> mapIn = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();
        String queueId = (String) mapIn.get("queueId");
        String tenantId = (String) mapIn.get("tenantId");

        HashMap<String, Object> queueMap = new HashMap<String, Object>();
        queueMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueMap);
        if (CollectionUtils.isEmpty(queueList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }
        FollowQueue fq = queueList.get(0);
        if (!Constants.QUEUE_STATUS_NOMAL.equals(fq.getQueueStatus())) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_STATUS_IRREGULAR, "当前加入的队列状态不正常，无法添加患者！"));
        }
        retOut.put("queueInfo", fq);
        /*
         * 租户id必须存在，一个用户加入某个租户下的队列，则记录一份用户信息， 同时记录一份基本用户信息， 基本用户信息tenant_id=0
         * add by DemonLee, 2017.6.11
         */
        if (StringUtils.isEmpty(tenantId)) {
            // session中没有，则从队列下获取，队列下没有，则报错
            tenantId = fq.getTenantId();
            if (StringUtils.isEmpty(tenantId)) {
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_FOR_TENANT_NOT_EXIST,
                        "租户id为空或未配置，无法添加患者！"));
            }
            retOut.put("tenantId", tenantId);
        }

        int targetNum = fq.getTargetNum();// 队列目标人数
        int currNum = fq.getCurrNum();// 队列当前人数
        if (Constants.QUEUE_TARGET_NUM_INFINITE == targetNum) {
            // -1表示不设上限，可以任意添加患者
        } else if (targetNum <= 0) {
            // 其他小于等于0的数不合理，异常退出
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_CONFIG_ERROR,
                    "当前队列【" + fq.getQueueName() + "】目标人数配置错误，无法添加新患者！"));
        } else if (currNum >= targetNum) {
            // 当前人数已达到目标人数，无法继续添加患者
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_TARGETNUM_LIMIT,
                    "当前队列【" + fq.getQueueName() + "】人数已达到上限，无法添加新患者！"));
        }

        return retOut;
    }

    /**
     * 患者队列实例信息校验
     */
    public Map<String, Object> dealPtQueueInfo(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> retOut = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(paramIn);
        String queueId = (String) mapIn.get("queueId");
        String userId = (String) mapIn.get("userId");
        String userName = (String) mapIn.get("userName");
        String queueName = (String) mapIn.get("queueName");
        String updateTime = (String) mapIn.get("updateTime");
        Map<String, Object> quesMap = ToolUtils.typeCast(mapIn.get("questiones"));
        PatientQueueScheme pts = (PatientQueueScheme) mapIn.get("ptQueueSchemeInfo");

        Map<String, Object> qryPqsMap = new HashMap<String, Object>();
        qryPqsMap.put("userId", userId);
        qryPqsMap.put("queueId", queueId);
        // 查询出暂停和正常 两个状态,如果查到暂停状态 则提示去恢复
        List<String> statulist = new ArrayList<String>();
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_SUSPEND);
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        // 待审核状态提示去审批
        statulist.add(Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT);
        qryPqsMap.put("status", statulist);

        List<PatientQueueScheme> pqsList = patientQueueSchemeDao.selectByUserId(qryPqsMap);
        if (null != pqsList && 0 != pqsList.size()) {
            if (Constants.PATIENT_QUEUESCHEME_USER_STATUS_SUSPEND.equals(pqsList.get(0).getUserStatus())) {
                logger.error("该患者[" + userName + "]在当前队列中为暂停状态，可直接恢复！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_STATUS_SUSPEND,
                        "该患者[" + userName + "]在当前队列中为暂停状态，请恢复患者为管理状态！"));
            } else if (Constants.PATIENT_QUEUESCHEME_USER_STATUS_AUDIT.equals(pqsList.get(0).getUserStatus())) {
                logger.error("该患者[" + userName + "]在当前队列中为待审核状态，请审批完再添加！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_STATUS_AUDIT,
                        "该患者[" + userName + "]在当前队列中为待审核状态，请进入审批列表审批即可"));
            } else {
                logger.error("患者[" + userName + "]已经加入[" + queueName + "]，请不要重复加入！");
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_ALREADY_EXIST,
                        "患者[" + userName + "]已经加入[" + queueName + "]，请不要重复加入！"));
            }
        }

        // 更新队列当前人数+1 fu_queue_info
        FollowQueue fqueueVo = new FollowQueue();
        fqueueVo.setCurrNum(1);
        fqueueVo.setId(queueId);
        fqueueVo.setUpdateTime(updateTime);
        queueDao.updateQueue(fqueueVo);

        // 查询问卷中是否有科研id（根据bs_static_param.type=1006配置的param_code匹配），需要入表pt_queuescheme_info.his_no字段
        if (MapUtils.isNotEmpty(quesMap)) {
            // 查询配置表中的配置的id
            Map<String, Object> staticMap = new HashMap<String, Object>();
            staticMap.put("type", Constants.CONTENT_DATA_TYPE);
            List<Map<String, Object>> quesList = confCacheDao.selectBsStaticParamByCondition(staticMap);
            if (!CollectionUtils.isEmpty(quesList)) {
                List<String> hisNoList = new ArrayList<String>();
                int kk = 0;
                int quesSize = quesList.size();
                Map<String, Object> confMap = new HashMap<String, Object>();
                for (kk = 0; kk < quesSize; kk++) {
                    confMap = quesList.get(kk);
                    String confId = (String) quesMap.get(confMap.get("paramCode"));
                    if (!StringUtils.isBlank(confId)) {
                        hisNoList.add(confId);
                    }
                }
                // 目前只考虑最大3个研究id
                int inum = hisNoList.size();
                for (kk = 0; kk < inum; kk++) {
                    if (0 == kk) {
                        pts.setHisNo1(hisNoList.get(kk));
                    } else if (1 == kk) {
                        pts.setHisNo2(hisNoList.get(kk));
                    } else if (2 == kk) {
                        pts.setHisNo3(hisNoList.get(kk));
                    } else {
                        logger.warn("ignore his_no[" + kk + "]==" + hisNoList.get(kk));
                    }
                }
            }
        }
        retOut.put("ptQueueSchemeInfo", pts);

        return retOut;
    }

    /**
     * 建档患者信息同步
     */
    public Map<String, Object> dealPtSynchInfo(Map<String, Object> paramIn) throws Exception {
        Map<String, Object> retOut = new HashMap<String, Object>();
        Map<String, Object> mapIn = new HashMap<String, Object>(paramIn);
        String ptSchemeId = (String) mapIn.get("ptSchemeId");
        String queueId = (String) mapIn.get("queueId");
        String authorId = (String) mapIn.get("authorId");
        String tenantId = (String) mapIn.get("tenantId");
        Integer redisFlag = (Integer) mapIn.get("redisFlag");
        String queueName = (String) mapIn.get("queueName");
        String deptId = (String) mapIn.get("deptId");
        String smsFlag = (String) mapIn.get("smsFlag");
        Patient pt = (Patient) mapIn.get("patientInfo");

        // redis记录今日新增患者
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

            if (1 == redisFlag) {
                ptQueueRedis.patientAddforQueue(queueId, jedis);
                ptQueueRedis.patientAddforAuthor(authorId, jedis);
                ptQueueRedis.patientAddforTenant(tenantId, jedis);
                if (!Constants.OP_TYPE_SELF.equals(pt.getSourceType())) {
                    ptQueueRedis.ptDoorAddforAuthor(authorId, jedis);
                }
            }
            // 建档，诊疗和随访都要更新今日门诊，userId※ptSchemeId※姓名
            int dealTime = Integer.parseInt(DateUtil.getHm());// 15:30-->1530
            Map<String, Object> redisMap = new HashMap<String, Object>();
            redisMap.put("queueId", queueId);
            redisMap.put("dealDate", DateUtil.getCurrDate());
            redisMap.put("userId", pt.getId());
            redisMap.put("ptSchemeId", ptSchemeId);
            redisMap.put("userName", pt.getUserName());
            redisMap.put("dealTime", dealTime);
            // 先更新诊疗，后续再增加更新随访
            ptQueueRedis.saveOutPatientRedisforQueue(redisMap, jedis);
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            ToolUtils.closeRedis(jedis);
        }

        // 发消息到 患者注册 消息队列topic 放在最后处理
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("tenantId", tenantId);
        map.put("code", Constants.SMS_TEMPLATE_REGISTER_TYPE);
        String smsContent = "";
        if (StringUtils.isBlank(smsFlag)) {
            smsFlag = "";
        }
        if (!Constants.QUEUE_PATIENT_REGISTER_NOT_SEND_SMS.equals(smsFlag)) {
            smsContent = bsSmsTemplateService.getSmsTemplateByCondition(map);
        }
        // 根据科室管理系统 科室id 查询 关联APP端 科室id 并同步给app
        DepartmentBasic dept = null;
        Map<String, String> paramMap = new HashMap<String, String>();
        paramMap.put("departmentId", deptId);// 随访科室ID
        paramMap.put("queueId", queueId);
        paramMap.put("queueName", queueName);

        String appDeptId = "";
        if (!StringUtils.isBlank(deptId)) {
            map.clear();
            map.put("deptId", deptId);
            dept = deparmentBasicDao.selectAppDeptId(map);
            if (null != dept) {
                appDeptId = String.valueOf(dept.getRefDepartmentId());
                paramMap.put("refDepartmentId", appDeptId);// app科室ID
            }
        }


        return retOut;
    }

    /**
     * 患者队列建档内容记录
     */
    public Map<String, Object> savePtQueueArchives(Map<String, Object> paramIn) throws Exception {
        logger.warn("---begin savePtQueueArchives---");
        Map<String, Object> servParamMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();

        String queueId = (String) servParamMap.get("queueId");
        String updateTime = (String) servParamMap.get("updateTime");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String userId = (String) servParamMap.get("userId");
        String ptQueueSchemeId = (String) servParamMap.get("ptQueueSchemeId");
        String archiveTaskId = (String) servParamMap.get("archiveTaskId");
        String authorId = (String) servParamMap.get("authorId");
        String tenantId = (String) servParamMap.get("tenantId");
        Map<String, Object> quesMap = ToolUtils.typeCast(servParamMap.get("contentData"));
        String sourceType = (String) servParamMap.get("sourceType");
        String ptArchiveTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);

        // 解析建档内容答案
        if (MapUtils.isEmpty(quesMap)) {
            logger.warn("无建档问卷问题--答案记录");
        } else {
            List<PtArchiveData> ptcInList = new ArrayList<PtArchiveData>();
            Iterator<String> iter = quesMap.keySet().iterator();
            String queskey = "";
            String quesvalue = "";
            while (iter.hasNext()) {
                PtArchiveData pcdVo = new PtArchiveData();
                queskey = iter.next();
                quesvalue = (String) quesMap.get(queskey);

                pcdVo.setCreateTime(updateTime);
                pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                pcdVo.setQuestionAnswer(quesvalue);
                pcdVo.setQuestionId(queskey);
                pcdVo.setQueueId(queueId);
                pcdVo.setTaskId(archiveTaskId);
                pcdVo.setUpdateAccept(updateAccept);
                pcdVo.setUpdateTime(updateTime);
                pcdVo.setUserId(userId);
                pcdVo.setPtSchemeId(ptQueueSchemeId);
                pcdVo.setPtTaskId(ptArchiveTaskId);
                pcdVo.setTenantId(tenantId);
                pcdVo.setSourceTypeCreate(sourceType);
                pcdVo.setSourceTypeUpdate(sourceType);
                ptcInList.add(pcdVo);
            }
            // 批量插入
            ptArchiveDataDao.savePtArchiveDataBatch(ptcInList);// pt_archivedata_info

            Map<String, Object> archMapIn = new HashMap<String, Object>();
            archMapIn.put("ptTaskId", ptArchiveTaskId);
            archMapIn.put("updateAccept", updateAccept);
            archMapIn.put("updateType", Constants.UPDATE_TYPE_INSERT);
            ptArchiveDataDao.savePtArchiveDataHis(archMapIn);// pt_archivedata_info_his
        }
        // 建档任务实例化
        PtArchiveTask ptArchiveTask = new PtArchiveTask();
        ptArchiveTask.setAuthorId(authorId);
        ptArchiveTask.setCreateTime(updateTime);
        ptArchiveTask.setFinishTime(updateTime);
        ptArchiveTask.setId(ptArchiveTaskId);
        ptArchiveTask.setNextAddress("");
        // ptArchiveTask.setNextDate();
        ptArchiveTask.setPtSchemeId(ptQueueSchemeId);
        ptArchiveTask.setQueueId(queueId);
        ptArchiveTask.setTaskId(archiveTaskId);
        ptArchiveTask.setTaskIntro("建档信息");
        ptArchiveTask.setTaskName("建档");
        ptArchiveTask.setTaskNote("");
        ptArchiveTask.setUpdateAccept(updateAccept);
        ptArchiveTask.setUpdateAuname("");
        ptArchiveTask.setUpdateAuthor(authorId);
        ptArchiveTask.setUpdateTime(updateTime);
        ptArchiveTask.setUserId(userId);
        // 诊间扫码渠道建档，需要审核，modify by DemonLee 2018.3.7
        ptArchiveTask.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL);
        if (StringUtils.isNotBlank(sourceType) && Constants.PATIENT_SOURCE_TYPE_SCAN.equals(sourceType)) {
            ptArchiveTask.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_CHECKING);
        }
        ptArchiveTaskDao.savePtArchiveTask(ptArchiveTask);// pt_archivetask_info
        Map<String, Object> archTaskIn = new HashMap<String, Object>();
        archTaskIn.put("id", ptArchiveTaskId);
        archTaskIn.put("updateType", Constants.UPDATE_TYPE_INSERT);
        ptArchiveTaskDao.savePtArchiveTaskHis(archTaskIn);

        retOut.put("ptArchiveTaskId", ptArchiveTaskId);

        // 同一租户下该患者是否加入过其他队列，若有则需要更新建档信息
        Map<String, Object> mapIn = new HashMap<String, Object>();
        Map<String, Object> oprInfo = new HashMap<String, Object>();
        Map<String, Object> taskInfo = new HashMap<String, Object>();
        mapIn.put("questions", quesMap);

        oprInfo.put("updateAccept", updateAccept);
        oprInfo.put("updateTime", updateTime);
        oprInfo.put("authorId", authorId);
        oprInfo.put("tenantId", tenantId);
        oprInfo.put("followQueueId", queueId);
        oprInfo.put("patientId", userId);
        oprInfo.put("ptSchemeId", ptQueueSchemeId);
        oprInfo.put("sourceType", sourceType);
        mapIn.put("oprInfo", oprInfo);

        taskInfo.put("ptTaskId", archiveTaskId);
        mapIn.put("taskInfo", taskInfo);

        patientArchService.dealOthQueuePtArchive(mapIn);

        return retOut;
    }

    /**
     * 患者科研随访任务实例化
     */
    public Map<String, Object> dealPtFuTaskIns(Map<String, Object> paramIn) throws Exception {
        logger.warn("---begin dealPtFuTaskIns---");
        Map<String, Object> servParamMap = new HashMap<String, Object>(paramIn);
        Map<String, Object> retOut = new HashMap<String, Object>();

        Patient pt = (Patient) servParamMap.get("patient");
        String queueId = (String) servParamMap.get("queueId");
        String updateTime = (String) servParamMap.get("updateTime");
        String authorId = (String) servParamMap.get("authorId");
        String updateAccept = (String) servParamMap.get("updateAccept");
        String authorName = (String) servParamMap.get("authorName");
        // String opType = (String) servParamMap.get("opType");
        String userId = (String) servParamMap.get("userId");
        String ptQueueSchemeId = (String) servParamMap.get("ptQueueSchemeId");
        String schemeVersionId = (String) servParamMap.get("schemeVersionId");
        if (StringUtils.isEmpty(pt.getId())) {
            pt.setId(userId);
        }
        String schemeId = (String) servParamMap.get("schemeId");
        Integer schemeBusiType = (Integer) servParamMap.get("schemeBusiType");
        String tenantId = (String) servParamMap.get("tenantId");

        // 查询当前队列对应方案门诊任务
        HashMap<String, Object> taskQueryParam = new HashMap<String, Object>();
        taskQueryParam.put("schemeVersionid", schemeVersionId);
        taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_SCHEDULE);// 0：门诊随访
        taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_FIRST);
        List<FollowTask> taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
        int breakFlag = 0;
        if (CollectionUtils.isEmpty(taskList)) {
            breakFlag = 1;
        }
        taskQueryParam.remove("seqNo");

        // 实例化方案下任务信息给具体患者
        List<PatientTask> ptTaskList = new ArrayList<PatientTask>();
        List<PatientTaskContent> ptTaskContentList = new ArrayList<PatientTaskContent>();
        // List<String> taskIdList = new ArrayList<String>();
        FollowTask ft = new FollowTask();
        int iPrenDay = pt.getPregnancyDay();
        String birthDay = pt.getBirthday();
        String currDay = DateUtil.getCurrDate();
        Map<String, Object> executeMapIn = new HashMap<String, Object>();
        executeMapIn.put("currDay", currDay);
        executeMapIn.put("prenDay", iPrenDay);
        executeMapIn.put("birthDay", birthDay);
        executeMapIn.put("ageDay", ToolUtils.getBirthAgeDay(birthDay));
        // 出院日期，暂无，先写上
        executeMapIn.put("outHospitalDay", servParamMap.get("outHospitalDay"));
        // 初检孕周（孕产妇随访）
        executeMapIn.put("firstChkPregWeek", servParamMap.get("firstChkPregWeek"));
        executeMapIn.put("lastMenstruationDate", servParamMap.get("lastMenstruationDate"));
        executeMapIn.put("deliveryDate", servParamMap.get("deliveryDate"));
        int suffWinDay = 0;// 后窗口期
        int iWinDay = 0;// 前窗口期
        String endTime = "";
        String nextTaskId = "";
        String currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
        int lostNum = 0;// 门诊随访失访任务数
        int onlineLostNum = 0;// 线上随访失访任务数
        String taskType = Constants.TASK_TYPE_SCHEME_SCHEDULE;
        int outTotal = 0;// 门诊随访总任务数
        int onlineTotal = 0;// 线上随访总任务数
        int iTaskSeq = 0;
        // 实例化门诊任务
        while (true) {
            if (0 == breakFlag) {
                ft = taskList.get(0);
                iTaskSeq = ft.getSeqNo();
                int iCycleDay = ft.getCycleDay();
                if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                    outTotal++;
                } else {
                    onlineTotal++;
                }

                // pt_task_info
                if (StringUtils.isEmpty(ft.getNextTaskId())) {
                    nextTaskId = "";
                } else {
                    nextTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
                }
                PatientTask ptk = new PatientTask();
                String ptk_id = currTaskId;
                // taskIdList.add(ptk_id);
                ptk.setId(ptk_id);
                ptk.setNextTaskId(nextTaskId);
                currTaskId = nextTaskId;

                // 触发方式
                String executeType = ft.getExecuteType();
                executeMapIn.put("executeType", executeType);
                executeMapIn.put("taskSeq", iTaskSeq);
                executeMapIn.put("cycleDay", iCycleDay);
                executeMapIn.put("executeDay", ft.getExecuteDay());
                String executeTime = ToolUtils.getExecuteTime(executeMapIn);
                iWinDay = ft.getWindowDay();
                suffWinDay = ft.getSuffixWindowDay();
                endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);

                if (Constants.TASK_SEQ_FOR_INIT == iTaskSeq && Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                    iWinDay = 0;// 建档任务无窗口期
                    suffWinDay = 0;
                    // 建档任务默认完成，并记下录入人姓名
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_FINISH);
                    ptk.setUpdateAuname(authorName);
                    ptk.setUpdateAuthor(authorId);
                } else if (endTime.compareTo(currDay) < 0) {
                    // 已过期
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_EXPIRED);
                    if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                        lostNum++;
                    } else {
                        onlineLostNum++;
                    }
                    // 入失访记录表
                    PtLostRd prdVo = new PtLostRd();
                    prdVo.setAuthorId(authorId);
                    prdVo.setCreateTime(updateTime);
                    prdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PT_LOST_ID));
                    prdVo.setLostDate(endTime);
                    prdVo.setPtSchemeid(ptQueueSchemeId);
                    prdVo.setQueueId(queueId);
                    prdVo.setReasonId("");
                    prdVo.setTaskId(ptk_id);
                    prdVo.setTaskName(ft.getTaskName());
                    prdVo.setUpdateAccept(updateAccept);
                    prdVo.setUpdateTime(updateTime);
                    prdVo.setUserId(userId);
                    patientTaskDao.savePatientLostInfo(prdVo);
                } else {
                    // 未开始
                    ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_INIT);
                }

                ptk.setAuthorId(authorId);
                ptk.setExecuteTime(executeTime);
                ptk.setBeginTime(DateUtil.calcDay(executeTime, "-", iWinDay));
                ptk.setEndTime(endTime);
                ptk.setCreateTime(updateTime);
                ptk.setExecuteDay(ft.getExecuteDay());
                ptk.setExecuteType(executeType);
                ptk.setInformFlag(ft.getInformFlag());
                ptk.setPtSchemeid(ptQueueSchemeId);
                ptk.setSeqNo(iTaskSeq);
                ptk.setTaskIntro(ft.getTaskIntro());
                ptk.setTaskName(ft.getTaskName());
                ptk.setUpdateTime(updateTime);
                ptk.setUserId(pt.getId());
                ptk.setWarnDay(ft.getWarnDay());
                ptk.setWindowDay(iWinDay);
                ptk.setQueueId(queueId);
                ptk.setUpdateAccept(updateAccept);
                if (!StringUtils.isBlank(ft.getTaskType())) {
                    ptk.setTaskType(ft.getTaskType());// 方案中任务
                } else {
                    ptk.setTaskType(Constants.TASK_TYPE_SCHEME_SCHEDULE);// 门诊任务
                }
                ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_INIT);// 初始化审核状态
                ptTaskList.add(ptk);

                // 查询当前任务对应的任务内容
                HashMap<String, Object> taskContentParam = new HashMap<String, Object>();
                taskContentParam.put("taskId", ft.getId());
                taskContentParam.put("schemeVersionid", schemeVersionId);
                List<FollowTaskContent> taskContList = followTaskContDao.selectByTaskId(taskContentParam);
                if (null == taskContList || 0 == taskContList.size()) {
                    continue;
                }

                FollowTaskContent ftc = new FollowTaskContent();
                int tc = 0;
                for (; tc < taskContList.size(); tc++) {
                    ftc = taskContList.get(tc);

                    // 获取内容模板
                    Map<String, Object> templMap = new HashMap<String, Object>();
                    templMap.put("id", ftc.getTemplId());
                    List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                    if (null == ctList || 0 == ctList.size()) {
                        throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "查询任务内容模板记录为空！");
                    }
                    ContentTempl conVo = ctList.get(0);

                    // 获取内容模板版本
                    HashMap<String, Object> contVerMap = new HashMap<String, Object>();
                    contVerMap.put("templId", ftc.getTemplId());
                    contVerMap.put("templVersion", ftc.getTemplVersion());
                    List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
                    if (null == ctvList || 0 == ctvList.size()) {
                        throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST,
                                "查询任务内容模板版本记录为空！");
                    }
                    ContentTemplVersion ctv = ctvList.get(0);

                    // pt_taskcontent_info
                    String ptkc_id = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTID);
                    PatientTaskContent ptc = new PatientTaskContent();
                    ptc.setCreateTime(updateTime);
                    ptc.setUpdateTime(updateTime);
                    ptc.setId(ptkc_id);
                    ptc.setTaskId(ptk_id);
                    ptc.setTemplVersionid(ctv.getId());
                    ptc.setUpdateAccept(updateAccept);
                    ptc.setTemplType(conVo.getTemplType());
                    ptc.setUserId(userId);
                    ptc.setPtSchemeid(ptQueueSchemeId);
                    ptc.setSeqNo(conVo.getSeqNo());

                    ptTaskContentList.add(ptc);
                }

                breakFlag = 0;
                if (StringUtils.isEmpty(ft.getNextTaskId())) {
                    breakFlag = 1;
                } else {
                    taskQueryParam.put("taskId", ft.getNextTaskId());
                    taskList = followTaskDao.selectFollowTaskByScheVerAndId(taskQueryParam);
                    if (CollectionUtils.isEmpty(taskList)) {
                        breakFlag = 1;
                    }
                }
            }
            if (1 == breakFlag) {
                breakFlag = 0;
                if (Constants.TASK_TYPE_SCHEME_SCHEDULE.equals(taskType)) {
                    // 继续实例化线上随访任务
                    taskType = Constants.TASK_TYPE_SCHEME_TEMP;
                    taskQueryParam.put("schemeVersionid", schemeVersionId);
                    taskQueryParam.put("taskType", Constants.TASK_TYPE_SCHEME_TEMP);// 1：线上随访
                    taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_FIRST);
                    taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
                    if (CollectionUtils.isEmpty(taskList)) {
                        break;
                    }
                    taskQueryParam.remove("seqNo");
                    currTaskId = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
                } else if (Constants.TASK_TYPE_SCHEME_TEMP.equals(taskType)) {
                    break;
                }
            }
        }
        logger.debug("onlineLostNum==" + onlineLostNum);
        logger.debug("onlineTotal==" + onlineTotal);

        // 批量插入，提高效率
        patientTaskDao.savePatientTaskBatch(ptTaskList);
        if (ptTaskContentList.size() > 0) {
            patientTaskConDao.savePatientTaskContentBatch(ptTaskContentList);
        }

        // 实例化线上主诉登记任务
        ptTaskList.clear();
        ptTaskContentList.clear();
        taskQueryParam.clear();
        taskList.clear();
        taskQueryParam.put("schemeVersionid", schemeVersionId);
        taskQueryParam.put("taskType", Constants.TASK_TYPE_NONSCHEME_REALTIME);// 2：线上主诉登记
        taskQueryParam.put("seqNo", Constants.TASK_SEQ_FOR_FIRST);
        taskList = followTaskDao.selectBySchemeVersionid(taskQueryParam);
        if (!CollectionUtils.isEmpty(taskList)) {
            ft = taskList.get(0);
            String ruleType = "";

            Map<String, Object> ruleInMap = new HashMap<String, Object>();
            ruleInMap.put("taskId", ft.getId());
            ruleInMap.put("schemeVersionid", schemeVersionId);
            List<FuTaskRule> taskRuleList = fuTaskRuleDao.getTaskRuleByUnq(ruleInMap);
            if (!CollectionUtils.isEmpty(taskRuleList)) {
                ruleType = taskRuleList.get(0).getRuleType();
            }
            if (StringUtils.isEmpty(ruleType)) {
                // 默认通用规则
                ruleType = Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON;
            }

            // pt_task_info
            String ptk_id = SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASKID);
            PatientTask ptk = new PatientTask();
            ptk.setRuleType(ruleType);
            ptk.setId(ptk_id);
            ptk.setNextTaskId("");

            // 触发方式
            String executeType = ft.getExecuteType();
            String executeTime = currDay;
            iWinDay = ft.getWindowDay();
            suffWinDay = ft.getSuffixWindowDay();
            endTime = DateUtil.calcDay(executeTime, "+", suffWinDay);
            ptk.setTaskStatus(Constants.PATIENT_TASK_STATUS_INIT);

            ptk.setAuthorId(authorId);
            ptk.setExecuteTime(executeTime);
            ptk.setBeginTime(DateUtil.calcDay(executeTime, "-", iWinDay));
            ptk.setEndTime(endTime);
            ptk.setCreateTime(updateTime);
            ptk.setExecuteDay(ft.getExecuteDay());
            ptk.setExecuteType(executeType);
            ptk.setInformFlag(ft.getInformFlag());
            ptk.setPtSchemeid(ptQueueSchemeId);
            ptk.setSeqNo(Constants.TASK_SEQ_FOR_FIRST);
            ptk.setTaskIntro(ft.getTaskIntro());
            ptk.setTaskName(ft.getTaskName());
            ptk.setUpdateTime(updateTime);
            ptk.setUserId(pt.getId());
            ptk.setWarnDay(ft.getWarnDay());
            ptk.setWindowDay(iWinDay);
            ptk.setQueueId(queueId);
            ptk.setUpdateAccept(updateAccept);
            ptk.setTaskType(ft.getTaskType());
            ptk.setAuditStatus(Constants.PATIENT_TASK_AUDIT_STATUS_INIT);// 初始化审核状态

            // 查询当前任务对应的任务内容
            HashMap<String, Object> taskContentParam = new HashMap<String, Object>();
            taskContentParam.put("taskId", ft.getId());
            taskContentParam.put("schemeVersionid", schemeVersionId);
            List<FollowTaskContent> taskContList = followTaskContDao.selectByTaskId(taskContentParam);
            if (CollectionUtils.isEmpty(taskContList)) {
                logger.error("【" + ft.getId() + "】对应任务内容未配置！");
                throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASKCONTENT_NOT_EXIST, "任务内容未配置！");
            }

            FollowTaskContent ftc = new FollowTaskContent();
            int tc = 0;
            String beginDate = "";
            String endDate = "";
            for (; tc < taskContList.size(); tc++) {
                ftc = taskContList.get(tc);

                // 获取内容模板
                Map<String, Object> templMap = new HashMap<String, Object>();
                templMap.put("id", ftc.getTemplId());
                List<ContentTempl> ctList = contentTemplDao.selectTemplById(templMap);
                if (CollectionUtils.isEmpty(ctList)) {
                    logger.error("【" + ftc.getTemplId() + "】查询任务内容模板记录为空！");
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPL_NOT_EXIST, "查询任务内容模板记录为空！");
                }
                ContentTempl conVo = ctList.get(0);

                // 获取内容模板版本
                HashMap<String, Object> contVerMap = new HashMap<String, Object>();
                contVerMap.put("templId", ftc.getTemplId());
                contVerMap.put("templVersion", ftc.getTemplVersion());
                List<ContentTemplVersion> ctvList = contentTemplDao.selectContentDataNoTextByTempl(contVerMap);
                if (CollectionUtils.isEmpty(ctvList)) {
                    logger.error("【" + ftc.getTemplId() + ", " + ftc.getTemplVersion() + "】查询任务内容模板版本记录为空！");
                    throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUES_TEMPLVERSION_NOT_EXIST,
                            "查询任务内容模板版本记录为空！");
                }
                ContentTemplVersion ctv = ctvList.get(0);

                // pt_taskcontent_info
                PatientTaskContent ptc = new PatientTaskContent();
                ptc.setCreateTime(updateTime);
                ptc.setUpdateTime(updateTime);
                ptc.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTID));
                ptc.setTaskId(ptk_id);
                ptc.setTemplVersionid(ctv.getId());
                ptc.setUpdateAccept(updateAccept);
                ptc.setTemplType(conVo.getTemplType());
                ptc.setUserId(userId);
                ptc.setPtSchemeid(ptQueueSchemeId);
                ptc.setSeqNo(conVo.getSeqNo());
                ptc.setRuleType(ruleType);
                ptc.setPriorityNo(ftc.getPriorityNo());

                // 通用版不需要考虑开始结束时间
                beginDate = currDay;
                endDate = currDay;
                if (!Constants.TASK_TYPE_SCHEME_SELFREPORT_COMMON.equals(ruleType)) {
                    // 按月龄来，需要计算
                    int beginDay = ftc.getBeginDay();
                    int endDay = ftc.getEndDay();
                    Map<String, Object> ruleCalcIn = new HashMap<String, Object>();
                    ruleCalcIn.put("beginDay", beginDay);
                    ruleCalcIn.put("endDay", endDay);
                    ruleCalcIn.put("ruleType", ruleType);
                    ruleCalcIn.put("birthday", birthDay);
                    ruleCalcIn.put("expectedDay", pt.getExpectedDay());
                    ruleCalcIn.put("currDay", currDay);
                    ruleCalcIn.put("prenDay", iPrenDay);
                    ruleCalcIn.put("ageDay", ToolUtils.getBirthAgeDay(birthDay));
                    ruleCalcIn.put("outHospitalDay", servParamMap.get("outHospitalDay"));
                    Map<String, Object> ruleCalcOut = ToolUtils.getTaskRuleTime(ruleCalcIn);
                    beginDate = (String) ruleCalcOut.get("beginDate");
                    endDate = (String) ruleCalcOut.get("endDate");
                }
                ptc.setBeginDate(beginDate);
                ptc.setEndDate(endDate);

                ptTaskContentList.add(ptc);
            }

            // 批量插入，提高效率
            patientTaskDao.save(ptk);
            if (ptTaskContentList.size() > 0) {
                patientTaskConDao.savePatientTaskContentBatch(ptTaskContentList);
            }
        }
        // 记录历史轨迹
        HashMap<String, Object> taskHisParam = new HashMap<String, Object>();
        taskHisParam.put("updateAccept", updateAccept);
        taskHisParam.put("updateType", Constants.UPDATE_TYPE_INSERT);
        taskHisParam.put("ptSchemeid", ptQueueSchemeId);
        taskHisParam.put("updateTime", updateTime);
        patientTaskDao.savePatientTaskHisByPtSchemeid(taskHisParam);

        // retOut.put("ptTaskSize", outTotal);
        // retOut.put("lostNum", lostNum);
        // retOut.put("onlineLostNum", onlineLostNum);
        // retOut.put("onlineTotal", onlineTotal);

        // pt_fuqueue_info
        PtFuQueue ptFuQueue = new PtFuQueue();
        ptFuQueue.setAuthorId(authorId);
        ptFuQueue.setCreateTime(updateTime);
        ptFuQueue.setFinishNum(0);
        ptFuQueue.setPtSchemeId(ptQueueSchemeId);
        ptFuQueue.setQueueId(queueId);
        ptFuQueue.setSchemeBusiType(schemeBusiType);
        ptFuQueue.setSchemeId(schemeId);
        ptFuQueue.setSchemeVersionid(schemeVersionId);
        ptFuQueue.setStatus(Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);
        ptFuQueue.setUpdateAccept(updateAccept);
        ptFuQueue.setUpdateAuthor(authorId);
        ptFuQueue.setUpdateTime(updateTime);
        ptFuQueue.setUserId(userId);
        ptFuQueue.setLostNum(lostNum);
        ptFuQueue.setTotalNum(outTotal);
        ptFuQueue.setTenantId(tenantId);
        ptFuQueueDao.savePtFuQueue(ptFuQueue);// pt_fuqueue_info
        Map<String, Object> ptFuQueueMapIn = new HashMap<String, Object>();
        ptFuQueueMapIn.put("ptSchemeId", ptQueueSchemeId);
        ptFuQueueMapIn.put("updateType", Constants.UPDATE_TYPE_INSERT);
        ptFuQueueDao.savePtFuQueueHis(ptFuQueueMapIn);// pt_fuqueue_info_his

        return retOut;
    }

    // 患者建档内容修改接口实现
    @Transactional
    public Map<String, Object> modifyPtArchivesData(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> argMap = new HashMap<String, Object>(paramMap);
        Map<String, Object> retOut = new HashMap<String, Object>();
        Map<String, Object> oprInfo = ToolUtils.typeCast(argMap.get("oprInfo")) ;
        Map<String, Object> taskInfo = ToolUtils.typeCast(argMap.get("taskInfo")) ;
        Map<String, Object> questions = ToolUtils.typeCast(argMap.get("questions"));

        String sourceType = (String) oprInfo.get("sourceType");// 来源渠道
        if (StringUtils.isBlank(sourceType)) {
            // 默认web端门诊渠道
            sourceType = Constants.PATIENT_SOURCE_TYPE_DOOR;
        }
        String opType = (String) oprInfo.get("opType");
        String opCode = (String) oprInfo.get("opCode");
        String opNote = (String) oprInfo.get("opNote");
        String updateAccept = (String) oprInfo.get("updateAccept");
        String updateTime = (String) oprInfo.get("updateTime");
        String authorId = (String) oprInfo.get("authorId");
        String authorName = (String) oprInfo.get("authorName");
        String tenantId = (String) oprInfo.get("tenantId");
        String deptId = (String) oprInfo.get("deptId");
        String queueId = (String) oprInfo.get("followQueueId");
        String userId = (String) oprInfo.get("patientId");
        String ptSchemeId = (String) oprInfo.get("ptSchemeId");
        String taskId = (String) taskInfo.get("ptTaskId");
        String updateAuname = (String) taskInfo.get("updateAuname");
        String taskNote = (String) taskInfo.get("taskNote");
        String nextDate = (String) taskInfo.get("nextDate");
        String nextAddress = (String) taskInfo.get("nextAddress");

        Map<String, Object> commMap = new HashMap<String, Object>();
        commMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        commMap.put("updateTime", updateTime);
        commMap.put("updateAccept", updateAccept);

        // 校验任务信息
        Map<String, Object> taskMapIn = new HashMap<String, Object>();
        taskMapIn.put("id", taskId);
        List<PtArchiveTask> ptVoList = ptArchiveTaskDao.listPtArchiveTask(taskMapIn);
        if (CollectionUtils.isEmpty(ptVoList)) {
            throw new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_TASK_NOT_EXIST, "该患者建档任务不存在！");
        }
        PtArchiveTask ptArchTaskVo = ptVoList.get(0);
        String taskAuditStatus = ptArchTaskVo.getAuditStatus();
        if (StringUtils.isBlank(taskAuditStatus)) {
            taskAuditStatus = Constants.PATIENT_TASK_AUDIT_STATUS_INIT;
        } else if (Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL.equals(taskAuditStatus)) {
            // 已审核通过
            if (Constants.PATIENT_SOURCE_TYPE_SCAN.equals(sourceType)) {
                // 诊间扫码渠道
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_PT_SACN_SYNC_DATA_FOR_AUDITED,
                        "建档信息医生已确认，患者无法同步修改！"));
            }
        }

        // 队列信息校验
        HashMap<String, Object> queueInMap = new HashMap<String, Object>();
        queueInMap.put("id", queueId);
        List<FollowQueue> queueList = queueDao.selectById(queueInMap);
        if (CollectionUtils.isEmpty(queueList)) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_QUEUE_NOT_EXIST, "未查询到对应队列信息！"));
        }
        FollowQueue fq = queueList.get(0);

        // 患者信息
        Map<String, Object> userInMap = new HashMap<String, Object>();
        userInMap.put("userId", userId);
        if (StringUtils.isEmpty(tenantId)) {
            tenantId = fq.getTenantId();
        }
        userInMap.put("tenantId", tenantId);
        Patient ptOut = patientDao.selectById(userInMap);
        if (null == ptOut) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }
        oprInfo.put("tenantId", tenantId);

        // 解析问卷答案内容
        if (MapUtils.isEmpty(questions)) {
            logger.warn("无问题--答案记录");
            return retOut;
        }

        // 建档任务需要考虑患者修改基本信息
        Map<String, Object> queueMap = new HashMap<String, Object>();
        Map<String, Object> userMapIn = new HashMap<String, Object>();
        String newPhoneNo = null; // 修改手机号码标志 true 需要同步app
        userMapIn.put("currPhoneNum", ptOut.getPhoneNo());
        userMapIn.put("updateAccept", updateAccept);
        userMapIn.put("userId", userId);
        userMapIn.put("updateTime", updateTime);
        userMapIn.put("tenantId", tenantId);
        userMapIn.put("contentData", questions);
        userMapIn.put("patient", ptOut);//2018-01-02
        queueMap = patientService.dealTaskContUserInfo(userMapIn);
        if (null != queueMap.get("newPhoneNo")) {
            newPhoneNo = (String) queueMap.get("newPhoneNo");
            queueMap.remove("newPhoneNo");
        }
        queueMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        queueMap.put("updateTime", updateTime);
        queueMap.put("updateAccept", updateAccept);

        // 更新之后，再查询患者基本信息
        ptOut = patientDao.selectById(userInMap);
        if (null == ptOut) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_NOT_EXIST, "查询无此患者记录！"));
        }
        String userName = ptOut.getUserName();

        // pt_queuescheme_info更新及历史轨迹变化记录
        queueMap.put("id", ptSchemeId);
        queueMap.put("updateAuthor", authorId);
        if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(sourceType)) {
            // 门诊渠道，审核确认
            queueMap.put("confirmFlag", Constants.PATIENT_QUEUESCHEME_USER_AUDIT_CONFIRM_SUCCESS);
        }
        int upret = patientQueueSchemeDao.updatePtQueueSchemeRecord(queueMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_QUEUE_NOT_EXIST, "患者队列实例无记录！"));
        }
        patientQueueSchemeDao.insertPatientQueueSchemeHis(queueMap);

        // 生长发育题型，调用接口:FamilyReportService.addGrowthRecord
        Map<String, Object> growthMapIn = new HashMap<String, Object>();
        growthMapIn.put("authorId", authorId);
        growthMapIn.put("userId", userId);
        growthMapIn.put("finishDate", DateUtil.getCurrDate2());// 完成日期待优化
        growthMapIn.put("tenantId", tenantId);
        growthMapIn.put("contentData", questions);
        patientService.dealGrowthDevApi(growthMapIn);

        // 入操作流水记录表 ia_operation_record
        Map<String, Object> paramRecord = new HashMap<String, Object>();
        paramRecord.put("userName", userName);
        paramRecord.put("userId", userId);
        paramRecord.put("queueId", queueId);
        paramRecord.put("authorId", authorId);
        paramRecord.put("opTime", updateTime);
        if (Constants.OP_TYPE_SELF.equals(opType)) {
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_8);
        } else {
            paramRecord.put("type", Constants.PATIENT_ACTIVE_BUSI_TYPE_9);
        }
        if (Constants.OP_TYPE_SELF.equals(opType)) {
            paramRecord.put("opUsertype", Constants.OPCODE_TYPE_PATIENT);
        } else {
            paramRecord.put("opUsertype", Constants.OPCODE_TYPE_DOCTOR);
        }
        paramRecord.put("authorName", authorName);
        paramRecord.put("opCode", opCode);
        paramRecord.put("updateAccept", updateAccept);
        paramRecord.put("tenantId", tenantId);
        paramRecord.put("remark", opNote);
        paramRecord.put("opType", opType);
        paramRecord.put("taskId", taskId);
        Map<String, Object> outRecord = patientInfoHisService.buildOperationRecord(paramRecord);
        patientOperationRecordDao.saveOperationRecord(outRecord);

        // 拼装问题和答案，逐条更新pt_archivedata_info
        List<PtArchiveData> ptcInList = new ArrayList<PtArchiveData>();
        Iterator<String> iter = questions.keySet().iterator();
        Map<String, Object> ptUpMapIn = new HashMap<String, Object>();
        int pr = 0;
        while (iter.hasNext()) {
            ptUpMapIn.clear();
            String queskey = iter.next();
            String quesvalue = (String) questions.get(queskey);

            ptUpMapIn.put("questionAnswer", quesvalue);
            ptUpMapIn.put("questionId", queskey);
            ptUpMapIn.put("ptTaskId", taskId);
            ptUpMapIn.put("updateAccept", updateAccept);
            ptUpMapIn.put("updateTime", updateTime);
            ptUpMapIn.put("sourceTypeUpdate", sourceType);
            pr = ptArchiveDataDao.modifyPtArchiveData(ptUpMapIn);
            if (0 == pr) {
                // 新增题型，需要插入
                PtArchiveData pcdVo = new PtArchiveData();
                pcdVo.setCreateTime(updateTime);
                pcdVo.setId(SeqUtil.getSeqNo(Constants.SEQ_NO_FOR_PTTASK_CONTDATAID));
                pcdVo.setQuestionAnswer(quesvalue);
                pcdVo.setQuestionId(queskey);
                pcdVo.setQueueId(queueId);
                pcdVo.setTaskId(ptArchTaskVo.getTaskId());
                pcdVo.setUpdateAccept(updateAccept);
                pcdVo.setUpdateTime(updateTime);
                pcdVo.setUserId(userId);
                pcdVo.setPtSchemeId(ptSchemeId);
                pcdVo.setPtTaskId(taskId);
                pcdVo.setTenantId(tenantId);
                pcdVo.setSourceTypeCreate(sourceType);
                pcdVo.setSourceTypeUpdate(sourceType);
                ptcInList.add(pcdVo);
            }
        }
        if (!CollectionUtils.isEmpty(ptcInList)) {
            ptArchiveDataDao.savePtArchiveDataBatch(ptcInList);
        }
        // 更新历史轨迹
        Map<String, Object> archMapIn = new HashMap<String, Object>();
        archMapIn.put("ptTaskId", taskId);
        archMapIn.put("updateAccept", updateAccept);
        archMapIn.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        ptArchiveDataDao.savePtArchiveDataHis(archMapIn);

        // pt_archivetask_info更新及历史轨迹变化
        Map<String, Object> taskMap = new HashMap<String, Object>(commMap);
        taskMap.put("id", taskId);
        taskMap.put("updateAuthor", authorId);
        taskMap.put("updateAuname", updateAuname);
        taskMap.put("updateTime", updateTime);
        taskMap.put("taskNote", taskNote);
        taskMap.put("nextDate", nextDate);
        taskMap.put("nextAddress", nextAddress);
        if (Constants.PATIENT_SOURCE_TYPE_DOOR.equals(sourceType)) {
            // 门诊渠道，审核确认
            taskMap.put("auditStatus", Constants.PATIENT_TASK_AUDIT_STATUS_NORMAL);
        } else if (Constants.PATIENT_TASK_AUDIT_STATUS_INIT.equals(taskAuditStatus)
                && Constants.PATIENT_SOURCE_TYPE_SCAN.equals(sourceType)) {
            // 诊间扫码渠道，初始化-->待审核
            taskMap.put("auditStatus", Constants.PATIENT_TASK_AUDIT_STATUS_CHECKING);
        } else {
            // 待扩展
        }
        upret = ptArchiveTaskDao.updatePtArchiveTaskById(taskMap);
        if (0 == upret) {
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_PATIENT_TASK_NOT_EXIST, "患者当前建档任务不存在！"));
        }
        taskMap.clear();
        taskMap.put("id", taskId);
        taskMap.put("updateType", Constants.UPDATE_TYPE_UPDATE_X);
        ptArchiveTaskDao.savePtArchiveTaskHis(taskMap);

        // 同一租户下该患者是否加入过其他队列，若有则需要更新建档信息
        patientArchService.dealOthQueuePtArchive(argMap);

        // redis 门诊新增
        if (Constants.OP_TYPE_DOOR.equals(opType)) {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                jedis.select(Constants.REDIS_DB_INDEX_PATIENT);
                ptQueueRedis.ptDoorAddforAuthor(authorId, jedis);

                // 入redis,userId※ptSchemeId
                Map<String, Object> redisMap = new HashMap<String, Object>();
                int dealTime = Integer.parseInt(DateUtil.getHm());// 15:30-->1530
                redisMap.put("queueId", queueId);
                redisMap.put("dealDate", DateUtil.getCurrDate());
                redisMap.put("userId", userId);
                redisMap.put("ptSchemeId", ptSchemeId);
                redisMap.put("userName", userName);
                redisMap.put("dealTime", dealTime);
                ptQueueRedis.saveOutPatientRedisforQueue(redisMap, jedis);
            } catch (JedisConnectionException jex) {
                logger.error("redis连接异常..." + jex.getMessage());
                throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
            } finally {
                ToolUtils.closeRedis(jedis);
            }
        }

        // 如手机号变更 同步APP（放在最后处理）
        if (StringUtils.isNotEmpty(newPhoneNo)) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("tenantId", tenantId);
            map.put("code", Constants.SMS_TEMPLATE_REGISTER_TYPE);
            String smsFlag = fq.getSmsFlag();
            if (StringUtils.isBlank(smsFlag)) {
                smsFlag = "";
            }
            String smsContent = "";
            if (!Constants.QUEUE_PATIENT_REGISTER_NOT_SEND_SMS.equals(smsFlag)) {
                smsContent = bsSmsTemplateService.getSmsTemplateByCondition(map);
            }
            DepartmentBasic dept = null;
            Map<String, String> param = new HashMap<String, String>();
            param.put("departmentId", deptId);// 随访科室ID
            param.put("queueId", queueId);

            String appDeptId = "";
            if (!StringUtils.isBlank(deptId)) {
                map.clear();
                map.put("deptId", deptId);
                dept = deparmentBasicDao.selectAppDeptId(map);
                if (null != dept) {
                    appDeptId = String.valueOf(dept.getRefDepartmentId());
                    param.put("refDepartmentId", appDeptId);// app科室ID
                }
            }
            ptOut.setPhoneNo(newPhoneNo);

        }

        return retOut;
    }

    // 患者诊疗建档答案信息查询
    public Map<String, Object> getPtArchInfo(Map<String, Object> paramMap) throws Exception {
        Map<String, Object> retOut = new HashMap<String, Object>();
        String ptSchemeId = (String) paramMap.get("ptSchemeId");
        String queueId = (String) paramMap.get("queueId");
        String ptTaskId = (String) paramMap.get("ptTaskId");
        String userId = (String) paramMap.get("userId");
        // String oriQueueId = (String) paramMap.get("oriQueueId");//
        // 原始队列id(处理同一租户不同队列的情况)

        // 患者选择的治疗方案list
        List<Map<String, Object>> schemeInfoList = new ArrayList<Map<String, Object>>();
        Map<String, Object> qrySchemeMap = new HashMap<String, Object>();
        Map<String, Object> schemeMapIn = new HashMap<String, Object>();
        schemeMapIn.put("ptSchemeId", ptSchemeId);
        schemeMapIn.put("status", Constants.TABLE_RECORD_STATUS_NOMAL);
        List<PtQueueSchemeRel> psRelList = ptQueueSchemeRelDao.listPtQueueSchemeRel(schemeMapIn);
        if (!CollectionUtils.isEmpty(psRelList)) {
            int relsize = psRelList.size();
            int rl = 0;
            PtQueueSchemeRel ptqsRelVo = new PtQueueSchemeRel();
            String schemeId = "";
            Integer schemeBusiType = 0;
            String schemeName = "";
            for (rl = 0; rl < relsize; rl++) {
                Map<String, Object> schemeInfo = new HashMap<String, Object>();
                ptqsRelVo = psRelList.get(rl);
                schemeId = ptqsRelVo.getSchemeId();
                schemeBusiType = ptqsRelVo.getSchemeBusiType();
                schemeInfo.put("schemeId", schemeId);
                schemeInfo.put("schemeBusiType", schemeBusiType);
                schemeInfo.put("schemeVersionid", ptqsRelVo.getSchemeVersionid());

                qrySchemeMap.clear();
                qrySchemeMap.put("schemeId", schemeId);
                qrySchemeMap.put("schemeBusiType", schemeBusiType);
                Map<String, Object> qrySchemeOut = this.getMultiSchemeInfo(qrySchemeMap);
                schemeName = (String) qrySchemeOut.get("schemeName");
                schemeInfo.put("schemeName", schemeName);

                schemeInfoList.add(schemeInfo);
            }
        }
        retOut.put("schemeList", schemeInfoList);

        // 患者扩展信息
        Map<String, Object> outExtMap = new HashMap<String, Object>();
        Map<String, Object> ptExtMap = new HashMap<String, Object>();
        ptExtMap.put("userId", userId);
        ptExtMap.put("queueId", queueId);
        List<PtUserextendInfo> ptextList = ptExtendDao.selectPtExtendInfo(ptExtMap);
        if (!CollectionUtils.isEmpty(ptextList)) {
            int iextNum = ptextList.size();
            int kk = 0;
            for (kk = 0; kk < iextNum; kk++) {
                PtUserextendInfo pextVo = ptextList.get(kk);
                outExtMap.put(pextVo.getParamName(), pextVo.getParamValue());
            }
        }
        retOut.put("extendInfo", outExtMap);

        // 患者建档问卷答案信息
        Map<String, Object> cntMap = new HashMap<String, Object>();
        cntMap.put("ptTaskId", ptTaskId);
        List<PtArchiveData> ptTaskConList = ptArchiveDataDao.listPtArchiveData(cntMap);
        HashMap<String, Object> questionMap = new HashMap<String, Object>();
        if (!CollectionUtils.isEmpty(ptTaskConList)) {
            int tt = 0;
            for (; tt < ptTaskConList.size(); tt++) {
                PtArchiveData pcdVo = ptTaskConList.get(tt);
                questionMap.put(pcdVo.getQuestionId(), pcdVo.getQuestionAnswer());
            }
        }
        retOut.put("values", questionMap);

        return retOut;
    }

    // 患者诊疗操作记录查询接口实现
    public Map<String, Object> listPtTrOperation(Map<String, Object> paramMap) throws Exception {
        HashMap<String, Object> argMap = new HashMap<String, Object>(paramMap);
        String flag = (String) argMap.get("flag");
        String invokeType = (String) argMap.get("invokeType");
        String noPaging = (String) argMap.get("noPaging");
        boolean appInvokeFlag = false;// app调用标志
        if (!StringUtils.isEmpty(invokeType)) {
            // app侧调用无租户id等信息
            appInvokeFlag = true;
            argMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
        }
        argMap.put("appInvokeFlag", appInvokeFlag);
        String userName = (String) argMap.get("userName");// 可以是姓氏或姓名
        if (null != userName && !"".equals(userName)) {
            argMap.put("userName", userName + "%");
        }

        int total = 0;
        Map<String, Object> retMap = new HashMap<String, Object>();
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        retMap.put("total", 0);
        retMap.put("rows", pqsList);

        // 若有服务号码或患者姓名，则先获取患者id串（可能有多个）
        Map<String, Object> userOutMap = this.dealQueryUserInfo(argMap);
        String chkUser = (String) userOutMap.get("chkUser");
        if ("0".equals(chkUser)) {
            return retMap;
        }

        // 根据当前登录账号获取，其可以查看的队列id（权限处理比较复杂，这里先简化）
        Map<String, Object> queueOutMap = this.dealQueryQueueAuthInfo(argMap);
        chkUser = (String) queueOutMap.get("chkUser");
        if ("0".equals(chkUser)) {
            return retMap;
        }
        argMap.put("queueIdIn", queueOutMap.get("queueIdIn"));

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            // 今日门诊记录flag=0（直接查询ia_operation_record.op_type=2|op_code=1000/1001）
            if ("0".equals(flag)) {
                if (StringUtils.isNotBlank(noPaging) && "Y".equals(noPaging)) {
                    // 不分页
                    argMap.remove("start");
                    argMap.remove("end");
                }
                Map<String, Object> listMapOut = this.listTrOutPatientByDate(argMap, jedis);
                total = (Integer) listMapOut.get("total");
                pqsList = ToolUtils.typeCast(listMapOut.get("rows"));
            }
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            ToolUtils.closeRedis(jedis);
        }

        retMap.put("total", total);
        retMap.put("rows", pqsList);

        return retMap;
    }

    // 患者基本信息校验
    public Map<String, Object> dealQueryUserInfo(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();
        mapOut.put("chkUser", "1");

        int qryUserFlag = 0;
        String patientId = (String) argMap.get("patientId");
        boolean appInvokeFlag = (boolean) argMap.get("appInvokeFlag");
        String tenantId = (String) argMap.get("tenantId");
        Map<String, Object> qryUserMap = new HashMap<String, Object>();
        if (!StringUtils.isEmpty(patientId)) {
            qryUserMap.put("userId", patientId);
            qryUserFlag = 1;
        }
        if (1 == qryUserFlag) {
            if (appInvokeFlag) {
                qryUserMap.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
            } else {
                qryUserMap.put("tenantId", tenantId);
            }
            List<Patient> ptList = patientDao.select(qryUserMap);
            if (CollectionUtils.isEmpty(ptList)) {
                logger.warn("无此患者信息...arg==" + qryUserMap.toString());
                mapOut.put("chkUser", "0");
                return mapOut;
            }
        }

        return mapOut;
    }

    // 按权限查询队列信息通用接口
    public Map<String, Object> dealQueryQueueAuthInfo(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();
        mapOut.put("chkUser", "1");

        String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        boolean appInvokeFlag = (boolean) argMap.get("appInvokeFlag");

        HashMap<String, Object> qryQueueMap = new HashMap<String, Object>();
        qryQueueMap.put("authorId", authorId);
        qryQueueMap.put("queueStatus", Constants.QUEUE_STATUS_NOMAL);// 队列状态正常
        qryQueueMap.put("tenantId", tenantId);
        qryQueueMap.put("queueTypePrivate", Constants.QUEUE_TYPE_PRIVATE);
        qryQueueMap.put("queueTypeTenant", Constants.QUEUE_TYPE_TENANT);
        qryQueueMap.put("queueTypePublic", Constants.QUEUE_TYPE_PUBLIC);

        List<FollowQueue> fqList = null;
        // 1：如果传入队列 则直接用队列查询 2：没有传入队列ID 则根据权限先查询 该用户有哪些队列权限 再查询
        String queueId = (String) argMap.get("queueId");
        if (appInvokeFlag) {
            if (!StringUtils.isBlank(queueId)) {
                Map<String, Object> queueMap = new HashMap<String, Object>();
                queueMap.put("id", queueId);
                fqList = queueDao.selectById(queueMap);
            }
        } else if (!StringUtils.isBlank(queueId)) {
            Map<String, Object> queueMap = new HashMap<String, Object>();
            queueMap.put("id", queueId);
            fqList = queueDao.selectById(queueMap);
        } else {
            fqList = queueDao.selectQueueIdByAuthority(qryQueueMap);
        }

        if (CollectionUtils.isEmpty(fqList)) {
            if (!appInvokeFlag) {
                logger.warn("该账号无可查看到的队列信息...arg==" + qryQueueMap.toString());
                mapOut.put("chkUser", "0");
                return mapOut;
            } else {
                logger.warn("该账号无可查看到的队列信息...app侧调用...");
            }
        } else {
            List<String> queueIdArray = new ArrayList<String>();
            int fqt = 0;
            for (; fqt < fqList.size(); fqt++) {
                FollowQueue fqVo = fqList.get(fqt);
                // 后续sql中用in条件处理（这里先不考虑返回结果超过1000个）
                queueIdArray.add(fqVo.getId());
            }

            // 获取随访患者list
            mapOut.put("queueIdIn", queueIdArray);
        }

        return mapOut;
    }

    // 今日门诊诊疗记录(sql版)
    public Map<String, Object> listTrOutPatientByDate(Map<String, Object> argMap, Jedis jedis) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();

        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        List<String> opCodeArr = new ArrayList<String>();
        opCodeArr.add(Constants.OP_CODE_1000);// 门诊建档
        opCodeArr.add(Constants.OP_CODE_1001);// 门诊录入
        argMap.put("opCodeArr", opCodeArr);
        argMap.put("opType", Constants.OP_TYPE_DOOR);
        argMap.put("currDay", DateUtil.getCurrDate());// 今日
        argMap.put("userStatus", Constants.PATIENT_QUEUESCHEME_USER_STATUS_NOMAL);// 队列中正常状态下的用户
        int total = ptTrOprDao.countTrOutPatientOpr(argMap);
        if (0 != total) {
            pqsList = ptTrOprDao.listTrOutPatientOpr(argMap);
            if (CollectionUtils.isEmpty(pqsList)) {
                total = 0;
            } else {
                int size = pqsList.size();
                int kk = 0;
                String pqsQueueId = "";
                Map<String, Object> qryMapIn = new HashMap<String, Object>();
                Map<String, Object> qryMapOut = new HashMap<String, Object>();
                for (kk = 0; kk < size; kk++) {
                    Map<String, Object> pqsMap = pqsList.get(kk);
                    // 获取队列名称
                    pqsQueueId = (String) pqsMap.get("followQueueId");
                    qryMapIn.clear();
                    qryMapIn.put("queueId", pqsQueueId);
                    qryMapOut = patientService.getQueueName(qryMapIn, jedis);
                    pqsMap.put("followQueueName", qryMapOut.get("queueName"));
                }
            }
        }
        mapOut.put("total", total);
        mapOut.put("rows", pqsList);

        return mapOut;
    }

    // 门诊操作记录查询接口实现(redis版）
    public Map<String, Object> listPtOutPatientOperByRedis(Map<String, Object> argMap) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();
        String flag = (String) argMap.get("flag");
        Map<String, Object> mapIn = new HashMap<String, Object>(argMap);

        long total = 0;
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        mapOut.put("total", total);
        mapOut.put("rows", pqsList);

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.select(Constants.REDIS_DB_INDEX_PATIENT);

            if ("0".equals(flag)) {
                // 今日门诊
                mapIn.put("dealDate", DateUtil.getCurrDate());
                mapOut = this.listOutPatientByRedis(mapIn, jedis);
            }
        } catch (JedisConnectionException jex) {
            logger.error("redis连接异常..." + jex.getMessage());
            throw (new AppException(ErrorCode.FOLLOWUP_EXCEPTION_TYPE_REDIS_CONNECT_ERROR, "Redis缓存连接失败!"));
        } finally {
            ToolUtils.closeRedis(jedis);
        }

        return mapOut;
    }

    // 今日门诊(redis版)
    public Map<String, Object> listOutPatientByRedis(Map<String, Object> argMap, Jedis jedis) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();

        Integer schemeBusiType = (Integer) argMap.get("schemeBusiType");
        Integer qryType = (Integer) argMap.get("qryType");
        String queueId = (String) argMap.get("queueId");
        String authorId = (String) argMap.get("authorId");
        String tenantId = (String) argMap.get("tenantId");
        Integer redisStart = (Integer) argMap.get("redisStart");
        Integer redisEnd = (Integer) argMap.get("redisEnd");
        String dealDate = (String) argMap.get("dealDate");

        long total = 0;
        List<Map<String, Object>> pqsList = new ArrayList<Map<String, Object>>();
        List<String> inList = new ArrayList<String>();
        String strKey = "";
        inList.add(Constants.REDIS_KEY_FOR_QUEUE_OUTPATIENT_TODAY);

        if (0 == qryType) {
            // 0 按登录账号查询
            inList.add(authorId);
        } else if (1 == qryType) {
            // 1 按队列查询
            inList.add(queueId);
        } else if (2 == qryType) {
            // 2 按租户查询
            inList.add(tenantId);
        }
        if (0 == schemeBusiType) {
            // 随访
            inList.add("" + Constants.SCHEME_BUSI_TYPE_0);
        } else if (1 == schemeBusiType) {
            // 诊疗
            inList.add("" + Constants.SCHEME_BUSI_TYPE_1);
        }

        inList.add(dealDate);
        strKey = ToolUtils.assembleKey(inList);
        total = jedis.zcard(strKey);
        if (total > 0) {
            Map<String, Object> mapIn = new HashMap<String, Object>();
            mapIn.put("strKey", strKey);
            mapIn.put("start", redisStart);
            mapIn.put("end", redisEnd);
            Map<String, Object> outRedisMap = ptQueueRedis.getOprInfoFromRedis(mapIn, jedis);
            outRedisMap.put("tenantId", tenantId);
            pqsList = this.listOutPatientByRedis(outRedisMap);
        }

        mapOut.put("total", total);
        mapOut.put("rows", pqsList);

        return mapOut;
    }

    // 处理redis返回结果，根据userId查询userName
    public List<Map<String, Object>> listOutPatientByRedis(Map<String, Object> mapIn) throws Exception {
        List<Map<String, Object>> listIn = ToolUtils.typeCast(mapIn.get("rows"));
        String tenantId = (String) mapIn.get("tenantId");
        int listSize = listIn.size();
        int ls = 0;

        String userId = "";
        Map<String, Object> userMapIn = new HashMap<String, Object>();
        List<Map<String, Object>> listOut = new ArrayList<Map<String, Object>>();
        Patient ptVo = new Patient();
        for (ls = 0; ls < listSize; ls++) {
            Map<String, Object> inMap = new HashMap<String, Object>();
            inMap = listIn.get(ls);
            userId = (String) inMap.get("patientId");
            userMapIn.put("userId", userId);
            userMapIn.put("tenantId", tenantId);
            ptVo = patientDao.selectById(userMapIn);
            if (null == ptVo) {
                userMapIn.put("tenantId", Constants.PT_USER_INFO_DEFAULT_TENANT_ID);
                ptVo = patientDao.selectById(userMapIn);
                if (null == ptVo) {
                    continue;
                }
            }
            inMap.put("patientName", ptVo.getUserName());

            listOut.add(inMap);
        }

        return listOut;
    }



    // 处理导入数据
    public Map<String, Object> EyesImport(Object workbook,Map<String, Object> argMap,String fileName) throws Exception {
        Map<String, Object> mapOut = new HashMap<String, Object>();
        for (int i = 0; i < 4; i++) {
        	if(workbook instanceof HSSFWorkbook ) {
        		DealWithEyesCreate.readExcel((HSSFWorkbook)workbook, i,fileName,argMap);
            }else if(workbook instanceof XSSFWorkbook) {
            	DealWithEyesCreate.readExcelXSSF((XSSFWorkbook)workbook, i,fileName,argMap);
            }
 	    }
        return mapOut;
    }


}
